package com.zmn.plat.business.impl.orderconfig.orderstock.channel;

import java.util.*;
import java.util.stream.Collectors;

import com.zmn.plat.common.dictionary.PlatErrorCodeDict;
import com.zmn.plat.common.exception.PlatException;
import com.zmn.plat.model.entity.channel.Channel;
import com.zmn.plat.services.interfaces.channel.ChannelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.collect.Lists;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.plat.business.interfaces.orderconfig.orderstock.channel.ChannelConfigCloseBService;
import com.zmn.plat.model.entity.orderconfig.orderstock.CategoryVO;
import com.zmn.plat.model.entity.orderconfig.orderstock.SubmitDutyDateVO;
import com.zmn.plat.model.entity.orderconfig.orderstock.channel.ChannelCloseDayVO;
import com.zmn.plat.model.entity.orderconfig.orderstock.channel.ChannelConfigClose;
import com.zmn.plat.model.entity.orderconfig.orderstock.channel.ChannelConfigCloseQuery;
import com.zmn.plat.services.interfaces.orderconfig.oderstock.channel.ChannelConfigCloseService;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;

@Slf4j
@Service
public class ChannelConfigCloseBServiceImpl implements ChannelConfigCloseBService {

    @Autowired
    private ChannelConfigCloseService channelConfigCloseService;
    @Autowired
    private ChannelService channelService;


    @Override
    @Cacheable(cacheNames = "redis5m", key = "'dubbo:channel:configclose:avaliable:channel:'+#p0+':status:'+#p1", unless = "#result == null || #result <= 0")
    public Integer getAvailableCategoryChannelId(Integer channelId, Integer status) {
        if(Objects.isNull(channelId)){
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }

        ChannelConfigCloseQuery query = new ChannelConfigCloseQuery();
        query.setChannelId(channelId);
        query.setStatus(status);
        List<ChannelConfigClose> list = channelConfigCloseService.listByQuery(query);
        if(CollectionUtils.isEmpty(list)){
            Channel channel = channelService.findByKey(channelId);
            if(Objects.isNull(channel)||Objects.isNull(channel.getParentId())){
                throw new PlatException(PlatErrorCodeDict.ERROR_CODE_ORDERCONFIG_STOCK_CHANNEL_NOT_AVALIABLE);
            }
            log.info("current channel is not config,return parent channelId.channelId:{},parentChannelID:{}",channelId,channel.getParentId());
            return channel.getParentId();
        }
        log.info("current channel is config,channelId:{}",channelId);
        return channelId;
    }

    @Override
    public void closeDays(SubmitDutyDateVO<ChannelCloseDayVO> vo) {
        ChannelCloseDayVO data = vo.getData();
        Integer channelId = data.getChannelId();
        List<CategoryVO> categorys = data.getCategorys();
        if (vo.getDays() != null && vo.getDays().size() > 0) {
            ChannelConfigCloseQuery query = new ChannelConfigCloseQuery();
            query.setChannelId(channelId);
            query.setCloseDayAfterOrEqCurrDay(true);
            Map<String, List<ChannelConfigClose>> closeMapByCategoryId =
                channelConfigCloseService.listByQuery(query).stream().collect(Collectors.groupingBy(item -> item.getServCategId() + "-" + item.getCategOneId() + "-" + item.getCategTwoId()));

            List<Integer> existsOpenIdList = Lists.newArrayList();
            List<ChannelConfigClose> insertList = categorys.stream().flatMap(categoryVO -> vo.getDays().stream().map(day -> {
                ChannelConfigClose newClose = new ChannelConfigClose();
                newClose.setChannelId(channelId);
                newClose.setServCategId(categoryVO.getServCategId());
                newClose.setCategOneId(categoryVO.getCategOneId());
                newClose.setCategTwoId(categoryVO.getCategTwoId());
                newClose.setDay(DateUtil.dateFormatToDate(day, DateUtil.FORMAT_DATE));
                newClose.setStatus(GlobalConsts.NO);
                newClose.setCreater(vo.getOperator());
                newClose.setCreateTime(DateUtil.getNow());
                newClose.setUpdater(vo.getOperator());
                newClose.setUpdateTime(DateUtil.getNow());
                return newClose;
            })).filter(item -> {
                List<ChannelConfigClose> closeList = closeMapByCategoryId.get(item.getServCategId() + "-" + item.getCategOneId() + "-" + item.getCategTwoId());
                if (closeList == null || closeList.stream().noneMatch(day -> day.getDay().equals(item.getDay()))) {
                    // 没有找到则新增
                    return true;
                }
                // 存在开启则修改为关闭status=1
                Optional<Integer> existsOpenId = closeList.stream().filter(day -> day.getDay().equals(item.getDay()) && day.getStatus() == GlobalConsts.YES).map(ChannelConfigClose::getId).findFirst();
                existsOpenId.ifPresent(id -> existsOpenIdList.add(id));
                return false;
            }).collect(Collectors.toList());

            if (insertList.size() > 0) {
                channelConfigCloseService.insertBatch(insertList);
            }
            if (existsOpenIdList.size() > 0) {
                for (Integer existsOpenId : existsOpenIdList) {
                    ChannelConfigClose modifyClose = new ChannelConfigClose();
                    modifyClose.setId(existsOpenId);
                    modifyClose.setStatus(GlobalConsts.NO);
                    modifyClose.setUpdater(vo.getOperator());
                    modifyClose.setUpdateTime(DateUtil.getNow());
                    channelConfigCloseService.updateByKey(modifyClose);
                }
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void openDays(List<Integer> ids, String operator) {
        for (Integer id : ids) {
            ChannelConfigClose open = new ChannelConfigClose();
            open.setId(id);
            open.setStatus(GlobalConsts.YES);
            open.setUpdater(operator);
            open.setUpdateTime(DateUtil.getNow());
            channelConfigCloseService.updateByKey(open);
        }
    }
}
